home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / ULARN.ARJ / ULARN.TAR / ularn / io.c < prev    next >
C/C++ Source or Header  |  1989-10-25  |  21KB  |  1,019 lines

  1. /* io.c    
  2.  *
  3.  *    Below are the functions in this file:
  4.  *
  5.  *    setupvt100()     Subroutine to set up terminal in correct mode for game
  6.  *    clearvt100()      Subroutine to clean up terminal when the game is over
  7.  *    getcharacter()     Routine to read in one character from the terminal
  8.  *    scbr()            Function to set cbreak -echo for the terminal
  9.  *    sncbr()            Function to set -cbreak echo for the terminal
  10.  *    newgame()     Subroutine to save the initial time and seed rnd()
  11.  *
  12.  *    FILE OUTPUT ROUTINES
  13.  *
  14.  *    lprintf(format,args . . .)    printf to the output buffer
  15.  *    lprint(integer)            send binary integer to output buffer
  16.  *    lwrite(buf,len)            write a buffer to the output buffer
  17.  *    lprcat(str)            sent string to output buffer
  18.  *
  19.  *    FILE OUTPUT MACROS (in header.h)
  20.  *
  21.  *    lprc(character)            put the character into the output buffer
  22.  *
  23.  *    FILE INPUT ROUTINES
  24.  *
  25.  *    long lgetc()            read one character from input buffer
  26.  *    long lrint()            read one integer from input buffer
  27.  *    lrfill(address,number)        put input bytes into a buffer
  28.  *    char *lgetw()            get a whitespace ended word from input
  29.  *    char *lgetl()            get a \n or EOF ended line from input
  30.  *
  31.  *    FILE OPEN / CLOSE ROUTINES
  32.  *
  33.  *    lcreat(filename)        create a new file for write
  34.  *    lopen(filename)            open a file for read
  35.  *    lappend(filename)        open for append to an existing file
  36.  *    lrclose()            close the input file
  37.  *    lwclose()            close output file
  38.  *    lflush()            flush the output buffer
  39.  *
  40.  *    Other Routines
  41.  *
  42.  *    cursor(x,y)        position cursor at [x,y]
  43.  *    cursors()        position cursor at [1,24] (saves memory)
  44.  *  cl_line(x,y)             Clear line at [1,y] and leave cursor at [x,y]
  45.  *  cl_up(x,y)            Clear screen from [x,1] to current line.
  46.  *  cl_dn(x,y)             Clear screen from [1,y] to end of display. 
  47.  *  standout(str)         Print the string in standout mode.
  48.  *  set_score_output()         Called when output should be literally printed.
  49.  ** putcharacter(ch)        Print one character in decoded output buffer.
  50.  ** flush_buf()            Flush buffer with decoded output.
  51.  ** init_term()            Terminal initialization -- setup termcap info
  52.  **char *tmcapcnv(sd,ss)      Routine to convert vt100 \33's to termcap format
  53.  *    beep()       Routine to emit a beep if enabled (see no-beep in .Ularnopts)
  54.  *
  55.  * Note: ** entries are available only in termcap mode.
  56.  */
  57. #include "header.h"
  58.  
  59. #ifdef BSD
  60. #    define    GTTY(arg)    (ioctl(0, TIOCGETP, arg))
  61. #    define    STTY(arg)    (ioctl(0, TIOCSETP, arg))
  62.     static struct sgttyb inittyb, curttyb;
  63. #else /* SYSV */
  64. #    define GTTY(arg)        (ioctl(0, TCGETA, arg))
  65. #    define STTY(arg)        (ioctl(0, TCSETAW, arg))
  66. #    define SPEED(x)    ((x).c_cflag & CBAUD)
  67.     static struct termio inittyb, curttyb;
  68. #endif /* BSD */
  69.  
  70. #define    ON    1
  71. #define OFF    0
  72.  
  73. extern short ospeed;
  74.  
  75. #define LINBUFSIZE 128        /* size of the lgetw() and lgetl() buffer */
  76. int lfd;            /*  output file numbers    */
  77. int fd;                /*  input file numbers    */
  78. static int ipoint=MAXIBUF,iepoint=MAXIBUF;    /*  input buffering pointers  */
  79. static char lgetwbuf[LINBUFSIZE];    /* get line (word) buffer*/
  80.  
  81. /*
  82.  *    setupvt100()         
  83.  *        Subroutine to set up terminal in correct mode for game
  84.  *    Attributes off, clear screen, set scrolling region, set tty mode 
  85.  */
  86. setupvt100()
  87. {
  88.     clear();  
  89.     setscroll();  
  90.     gettty();
  91. }
  92.  
  93. /*
  94.  *    clearvt100()          
  95.  *        Subroutine to clean up terminal when the game is over
  96.  *    Attributes off, clear screen, unset scrolling region, restore tty mode 
  97.  */
  98. clearvt100()
  99. {
  100.     resetscroll();  
  101.     clear();  
  102.     settty();
  103. }
  104.  
  105. /*
  106. **    gettty
  107. **
  108. ** Get initial state of terminal, set ospeed (for termcap routines)
  109. ** and switch off tab expansion
  110. */
  111. gettty()
  112. {
  113.     if(GTTY(&inittyb) < 0) {
  114.         fprintf(stderr, "OOPS: gettty failed\n");
  115.         fflush(stderr);
  116.         return;
  117.     }
  118.     curttyb = inittyb;
  119. #ifndef BSD
  120.     ospeed = SPEED(inittyb);
  121.     /* do not expand tabs - they might be needed inside a cm sequence */
  122.     if(curttyb.c_oflag & TAB3) {
  123.         curttyb.c_oflag &= ~TAB3;
  124.         setctty();
  125.     }
  126. #endif /* BSD */
  127.     setuptty();
  128. }
  129.  
  130. /*
  131. **    settty
  132. **
  133. **         reset terminal to original state 
  134. */
  135. settty() 
  136. {
  137.     if(STTY(&inittyb) < 0) {
  138.         fprintf(stderr, "OOPS: settty failed\n");
  139.         fflush(stderr);
  140.     }
  141. }
  142.  
  143. /*
  144. **    setctty
  145. **
  146. **        set current tty
  147. */
  148. setctty(){
  149.     if(STTY(&curttyb) < 0) {
  150.         fprintf(stderr, "OOPS: setctty failed\n");
  151.         fflush(stderr);
  152.     }
  153. }
  154.  
  155.  
  156. /*
  157. **
  158. **    function to setup all required terminal modes for game
  159. */
  160. setuptty(){
  161.     int change = 0;
  162. #ifdef BSD
  163.     scbr();
  164. #else /* SYSV */
  165.     if((curttyb.c_lflag & ECHO) != OFF){
  166.         curttyb.c_lflag &= ~ECHO;
  167.         change++;
  168.     }
  169.     if((curttyb.c_lflag & ICANON) != !(ICANON)){
  170.         curttyb.c_lflag &= ~ICANON;
  171.         curttyb.c_lflag |= !(ICANON);
  172.         /* be satisfied with one character; no timeout */
  173.         curttyb.c_cc[VMIN] = 1;        /* was VEOF */
  174.         curttyb.c_cc[VTIME] = 0;    /* was VEOL */
  175.         change++;
  176.     }
  177.     if(change)
  178.         setctty();
  179. #endif /* BSD */
  180. }
  181.  
  182. /*
  183.  *    scbr()        Function to set cbreak -echo for the terminal
  184.  *
  185.  *    like: system("stty cbreak -echo")
  186.  */
  187. scbr()
  188. {
  189. #ifdef BSD
  190.     curttyb.sg_flags |= CBREAK;
  191.     curttyb.sg_flags &= ~ECHO;
  192. #else /* SYSV */
  193.     curttyb.c_lflag &= ~ECHO;
  194.     curttyb.c_lflag &= ~ICANON;
  195. #endif /* BSD */
  196.     setctty();
  197. }
  198.  
  199. /*
  200.  *    sncbr()        Function to set -cbreak echo for the terminal
  201.  *
  202.  *    like: system("stty -cbreak echo")
  203.  */
  204. sncbr()
  205. {
  206. #ifdef BSD
  207.      curttyb.sg_flags &= ~CBREAK;
  208.     curttyb.sg_flags |= ECHO;
  209. #else /* SYSV */
  210.     curttyb.c_lflag |= ECHO;
  211.     curttyb.c_lflag |= ICANON;
  212. #endif /* BSD */
  213.     setctty();
  214. }
  215.  
  216. /*
  217.  *    getcharacter()     Routine to read in one character from the terminal
  218.  */
  219. getcharacter()
  220. {
  221.     char byt;
  222.  
  223.     lflush();        /* be sure output buffer is flushed */
  224.     read(0,&byt,1);     /* get byte from terminal */
  225.     return(byt);
  226. }
  227.  
  228. /*
  229.  *    newgame()         
  230.  *        Subroutine to save the initial time and seed rnd()
  231.  */
  232. newgame()
  233. {
  234.     register long *p,*pe;
  235.  
  236.     for (p=c,pe=c+100; p<pe; *p++ =0)
  237.         ;
  238.     time(&initialtime);        
  239.     srand(initialtime);
  240.     lcreat((char*)0);    /* open buffering for output to terminal */
  241. }
  242.  
  243. /*
  244.  *    lprintf(format,args . . .)        printf to the output buffer
  245.  *        char *format;
  246.  *        ??? args . . .
  247.  *
  248.  *    Enter with the format string in "format", as per printf() usage
  249.  *        and any needed arguments following it
  250.  *Note: lprintf() only supports %s, %c and %d, with width modifier and left
  251.  *    or right justification.
  252.  *    No correct checking for output buffer overflow is done, but flushes 
  253.  *        are done beforehand if needed.
  254.  *    Returns nothing of value.
  255.  */
  256. /*VARARGS*/
  257. lprintf(va_alist)
  258. va_dcl
  259. {
  260.     va_list ap;    /* pointer for variable argument list */
  261.     char *fmt;
  262.     char *outb,*tmpb;
  263.     long wide,left,cont,n;        /* data for lprintf    */
  264.     char db[12];            /* %d buffer in lprintf    */
  265.  
  266.     va_start(ap);    /* initialize the var args pointer */
  267.     fmt = va_arg(ap, char *);    /* pointer to format string */
  268.     if (lpnt >= lpend) lflush(); 
  269.     outb = lpnt;
  270.     for ( ; ; ) {
  271.         while (*fmt != '%')
  272.             if (*fmt) *outb++ = *fmt++;  
  273.             else { 
  274.                 lpnt=outb;  
  275.                 return; 
  276.             }
  277.         wide = 0;    
  278.         left = 1;    
  279.         cont=1;
  280.         while (cont)
  281.             switch(*(++fmt)) {
  282.             case 'd':    
  283.                 n = va_arg(ap, long);
  284.                 if (n<0) { 
  285.                     n = -n;  
  286.                     *outb++ = '-';  
  287.                     if (wide) --wide; 
  288.                 }
  289.                 tmpb = db+11;    
  290.                 *tmpb = (char)(n % 10 + '0');
  291.                 while (n>9)  
  292.                     *(--tmpb) = (char)((n /= 10) % 10+'0');
  293.                 if (wide==0)  
  294.                     while (tmpb < db+12) 
  295.                         *outb++ = *tmpb++;
  296.                 else {
  297.                     wide -= db-tmpb+12;
  298.                     if (left)  
  299.                         while (wide-- > 0) 
  300.                             *outb++ = ' ';
  301.                     while (tmpb < db+12) 
  302.                         *outb++ = *tmpb++;
  303.                     if (left==0)  
  304.                         while (wide-- > 0) 
  305.                             *outb++ = ' ';
  306.                 }
  307.                 cont=0;    
  308.                 break;
  309.  
  310.             case 's':    
  311.                 tmpb = va_arg(ap, char *);
  312.                 if (wide==0)  { 
  313.                     while (*outb++ = *tmpb++);  
  314.                     --outb; 
  315.                 } 
  316.                 else {
  317.                     n = wide - strlen(tmpb);
  318.                     if (left)  
  319.                         while (n-- > 0) 
  320.                             *outb++ = ' ';
  321.                     while (*outb++ = *tmpb++)
  322.                         ;  
  323.                     --outb;
  324.                     if (left==0)  
  325.                         while (n-- > 0) 
  326.                             *outb++ = ' ';
  327.                 }
  328.                 cont=0;    
  329.                 break;
  330.  
  331.             case 'c':    
  332.                 *outb++ = va_arg(ap, int);    
  333.                 cont=0;  
  334.                 break;
  335.  
  336.             case '0':
  337.             case '1':
  338.             case '2':
  339.             case '3':
  340.             case '4':
  341.             case '5':
  342.             case '6':
  343.             case '7':
  344.             case '8':
  345.             case '9':    
  346.                 wide = 10*wide + *fmt - '0';    
  347.                 break;
  348.             case '-':    
  349.                 left = 0;    
  350.                 break;
  351.             default:    
  352.                 *outb++ = *fmt;  
  353.                 cont=0;    
  354.                 break;
  355.             };
  356.         fmt++;
  357.     }
  358.     va_end(ap);
  359. }
  360.  
  361. /*
  362.  *    lprint(long-integer)                
  363.  *        long integer;
  364.  *
  365.  *        send binary integer to output buffer
  366.  *
  367.  *    +---------+---------+---------+---------+
  368.  *    |   high  |        |          |      low    |
  369.  *    |  order  |        |          |  order    |
  370.  *    |   byte  |        |          |      byte    |
  371.  *    +---------+---------+---------+---------+
  372.  *     31 --- 24 23 --- 16 15 ---  8 7  ---  0
  373.  *
  374.  *    The save order is low order first, to high order (4 bytes total)
  375.  *        and is written to be system independent.
  376.  *    No checking for output buffer overflow is done, but flushes if needed!
  377.  *    Returns nothing of value.
  378.  */
  379. lprint(x)
  380. long x;
  381. {
  382.     if (lpnt >= lpend) 
  383.         lflush();
  384.     *lpnt++ =  255 & x;            
  385.     *lpnt++ =  255 & (x>>8);
  386.     *lpnt++ =  255 & (x>>16);    
  387.     *lpnt++ =  255 & (x>>24);
  388. }
  389.  
  390. /*
  391.  *    lwrite(buf,len)                    
  392.  *        char *buf;
  393.  *        int len;
  394.  *    
  395.  *        write a buffer to the output buffer
  396.  *
  397.  *    Enter with the address and number of bytes to write out
  398.  *    Returns nothing of value
  399.  */
  400. lwrite(buf,len)
  401. char *buf;
  402. int len;
  403. {
  404.     register char *str;
  405.     register int num2;
  406.  
  407.     if (len > 399)  /* don't copy data if can just write it */
  408.     {
  409.         for (str=buf;  len>0; --len)
  410.             lprc(*str++);
  411.         lflush();
  412.         write(lfd,buf,len);
  413.     } 
  414.     else while (len) {
  415.         if (lpnt >= lpend) 
  416.             lflush();    /* if buffer is full flush it    */
  417.  
  418.         /*    # bytes left in output buffer    */
  419.         num2 = lpbuf+BUFBIG-lpnt;    
  420.  
  421.         if (num2 > len) num2=len;
  422.         str = lpnt;  
  423.         len -= num2;
  424.         while (num2--)  *str++ = *buf++;    /* copy in the bytes */
  425.         lpnt = str;
  426.     }
  427. }
  428.  
  429. /*
  430.  *    long lgetc()            Read one character from input buffer
  431.  *
  432.  *  Returns 0 if EOF, otherwise the character
  433.  */
  434. long lgetc()
  435. {
  436.     int i;
  437.  
  438.     if (ipoint != iepoint)  
  439.         return(inbuffer[ipoint++]);
  440.     if (iepoint!=MAXIBUF)   
  441.         return(0);
  442.     if ((i=read(fd,inbuffer,MAXIBUF))<=0) {
  443.         if (i!=0)  
  444.             fprintf(stderr,"error reading from input file\n");
  445.         iepoint = ipoint = 0;        
  446.         return(0);
  447.     }
  448.     ipoint=1;  
  449.     iepoint=i;  
  450.     return(*inbuffer);
  451. }
  452.  
  453. /*
  454.  *    long lrint()            Read one integer from input buffer
  455.  *
  456.  *        +---------+---------+---------+---------+
  457.  *        |  high   |        |          |   low   |
  458.  *        |  order  |        |          |  order    |
  459.  *        |   byte  |        |          |      byte    |
  460.  *        +---------+---------+---------+---------+
  461.  *            31  ---  24 23 --- 16 15 ---  8 7  ---   0
  462.  *
  463.  *    The save order is low order first, to high order (4 bytes total)
  464.  *    Returns the int read
  465.  */
  466. long lrint()
  467. {
  468.     unsigned long i;
  469.  
  470.     i  = 255 & lgetc();                
  471.     i |= (255 & lgetc()) << 8;
  472.     i |= (255 & lgetc()) << 16;        
  473.     i |= (255 & lgetc()) << 24;
  474.     return(i);
  475. }
  476.  
  477. /*
  478.  *    lrfill(address,number)            put input bytes into a buffer
  479.  *        char *address;
  480.  *        int number;
  481.  *
  482.  *    Reads "number" bytes into the buffer pointed to by "address".
  483.  *    Returns nothing of value
  484.  */
  485. lrfill(adr,num)
  486. char *adr;
  487. int num;
  488. {
  489.     char *pnt;
  490.     int num2;
  491.  
  492.     while (num) {
  493.         if (iepoint == ipoint) {
  494.             if (num>5) {
  495.                 if (read(fd,adr,num) != num)
  496.                     fprintf(stderr,"error reading from input file\n");
  497.                 num=0;
  498.             }
  499.             else { 
  500.                 *adr++ = lgetc();  
  501.                 --num; 
  502.             }
  503.         }
  504.         else {
  505.         /*    # of bytes left in the buffer    */
  506.             num2 = iepoint-ipoint;    
  507.  
  508.             if (num2 > num) 
  509.                 num2=num;
  510.             pnt = inbuffer+ipoint;    
  511.             num -= num2;  
  512.             ipoint += num2;
  513.             while (num2--)  
  514.                 *adr++ = *pnt++;
  515.         }
  516.     }
  517. }
  518.  
  519. /*
  520.  *    char *lgetw()            Get a whitespace ended word from input
  521.  *
  522.  *    Returns pointer to a buffer that contains word.  If EOF, returns a 0
  523.  */
  524. char *lgetw()
  525. {
  526.     char *lgp,cc;
  527.     int n=LINBUFSIZE,quote=0;
  528.  
  529.     lgp = lgetwbuf;
  530.  
  531.     do 
  532.         cc=lgetc();
  533.     while ((cc <= ' ') && (cc > 0));  /* eat whitespace */
  534.  
  535.     for ( ; ; --n,cc=lgetc()) {
  536.         if ((cc==0) && (lgp==lgetwbuf))  return(0);    /* EOF */
  537.         if ((n<=1) || ((cc<=32) && (quote==0))) { 
  538.             *lgp=0; 
  539.             return(lgetwbuf); 
  540.         }
  541.         if (cc != '"') *lgp++ = cc;   
  542.         else quote ^= 1;
  543.     }
  544. }
  545.  
  546. /*
  547.  *    char *lgetl()    
  548.  *         Function to read in a line ended by newline or EOF
  549.  *
  550.  *Returns pointer to a buffer that contains the line.  If EOF, returns 0
  551.  */
  552. char *lgetl()
  553. {
  554.     int i=LINBUFSIZE,ch;
  555.     char *str=lgetwbuf;
  556.  
  557.     for ( ; ; --i) {
  558.         if ((*str++ = ch = lgetc()) == 0) {
  559.             if (str == lgetwbuf+1)  return(0); /* EOF */
  560. ot:    
  561.             *str = 0;    
  562.             return(lgetwbuf);    /* line ended by EOF */
  563.         }
  564.         if ((ch=='\n') || (i<=1))  
  565.             goto ot; /* line ended by \n */
  566.     }
  567. }
  568.  
  569. /*
  570.  *    lcreat(filename)            Create a new file for write
  571.  *        char *filename;
  572.  *
  573.  *    lcreat((char*)0); means to the terminal
  574.  *    Returns -1 if error, otherwise the file descriptor opened.
  575.  */
  576. lcreat(str)
  577. char *str;
  578. {
  579.     lpnt = lpbuf;    
  580.     lpend = lpbuf+BUFBIG;
  581.     if (str==0) return(lfd=1);
  582.     if ((lfd=creat(str,0644)) < 0) {
  583.         lfd=1; 
  584.         lprintf("error creating file <%s>\n",str); 
  585.         lflush(); 
  586.         return(-1);
  587.     }
  588.     return(lfd);
  589. }
  590.  
  591. /*
  592.  *    lopen(filename)            Open a file for read
  593.  *        char *filename;
  594.  *
  595.  *    lopen(0) means from the terminal
  596.  *    Returns -1 if error, otherwise the file descriptor opened.
  597.  */
  598. lopen(str)
  599. char *str;
  600. {
  601.     ipoint = iepoint = MAXIBUF;
  602.     if (str==0) return(fd=0);
  603.     if ((fd=open(str,0)) < 0) {
  604.         lwclose(); 
  605.         lfd=1; 
  606.         lpnt=lpbuf; 
  607.         return(-1);
  608.     }
  609.     return(fd);
  610. }
  611.  
  612. /*
  613.  *    lappend(filename)        Open for append to an existing file
  614.  *        char *filename;
  615.  *
  616.  *    lappend(0) means to the terminal
  617.  *    Returns -1 if error, otherwise the file descriptor opened.
  618.  */
  619. lappend(str)
  620. char *str;
  621. {
  622.     lpnt = lpbuf;    
  623.     lpend = lpbuf+BUFBIG;
  624.     if (str==0) return(lfd=1);
  625.     if ((lfd=open(str,2)) < 0) {
  626.         lfd=1; 
  627.         return(-1);
  628.     }
  629.     lseek(lfd,0,2);    /* seek to end of file */
  630.     return(lfd);
  631. }
  632.  
  633. /*
  634.  *    lrclose()                        
  635.  *            close the input file
  636.  *
  637.  *    Returns nothing of value.
  638.  */
  639. lrclose()
  640. {
  641.     if (fd > 0) close(fd);
  642. }
  643.  
  644. /*
  645.  *    lwclose()            close output file flushing if needed
  646.  *
  647.  *    Returns nothing of value.
  648.  */
  649. lwclose()
  650. {
  651.     lflush();    
  652.     if (lfd > 2) close(lfd);
  653. }
  654.  
  655. /*
  656.  *    lprcat(string)            append a string to the output buffer
  657.  *                    avoids calls to lprintf (time consuming)
  658.  */
  659. lprcat(str)
  660. char *str;
  661. {
  662.     char *str2;
  663.  
  664.     if (lpnt >= lpend) 
  665.         lflush(); 
  666.     str2 = lpnt;
  667.     while (*str2++ = *str++)
  668.         ;
  669.     lpnt = str2 - 1;
  670. }
  671.  
  672. /*
  673.  * cursor(x,y)      Put cursor at specified coordinates staring at [1,1] (termcap)
  674.  */
  675. cursor (x,y)
  676. int x,y;
  677. {
  678.     if (lpnt >= lpend) lflush ();
  679.  
  680.     *lpnt++ = CURSOR;        
  681.     *lpnt++ = x;        
  682.     *lpnt++ = y;
  683. }
  684.  
  685. /*
  686.  *    Routine to position cursor at beginning of 24th line
  687.  */
  688. cursors()
  689. {
  690.     cursor(1,24);
  691. }
  692.  
  693. /*
  694.  * Warning: ringing the bell is control code 7. Don't use in defines.
  695.  * Don't change the order of these defines.
  696.  * Also used in helpfiles. Codes used in helpfiles should be \E[1 to \E[7 with
  697.  * obvious meanings.
  698.  */
  699.  
  700. static char cap[256];
  701. char *CM, *CE, *CD, *CL, *SO, *SE, *AL, *DL;/* Termcap capabilities */
  702. static char *outbuf=0;    /* translated output buffer */
  703.  
  704. int putcharacter ();
  705.  
  706. /*
  707.  * init_term()        Terminal initialization -- setup termcap info
  708.  */
  709. init_term()
  710. {
  711.     char termbuf[1024];
  712.     char *capptr = cap+10;
  713.     char *term;
  714.  
  715.     switch (tgetent(termbuf, term = getenv("TERM"))) {
  716.     case -1: 
  717.         fprintf(stderr, "Cannot open termcap file.\n"); 
  718.         fflush(stderr);
  719.         exit(1);
  720.     case 0: 
  721.         fprintf(stderr, "Cannot find entry of ");
  722.         fprintf(stderr, term);
  723.         fprintf(stderr, " in termcap\n");
  724.         fflush(stderr);
  725.         exit(1);
  726.     };
  727.  
  728.     CM = tgetstr("cm", &capptr);  /* Cursor motion */
  729.     CE = tgetstr("ce", &capptr);  /* Clear to eoln */
  730.     CL = tgetstr("cl", &capptr);  /* Clear screen */
  731.  
  732.     /* OPTIONAL */
  733.     AL = tgetstr("al", &capptr);  /* Insert line */
  734.     DL = tgetstr("dl", &capptr);  /* Delete line */
  735.     SO = tgetstr("so", &capptr);  /* Begin standout mode */
  736.     SE = tgetstr("se", &capptr);  /* End standout mode */
  737.     CD = tgetstr("cd", &capptr);  /* Clear to end of display */
  738.  
  739.     if (!CM)    /* can't find cursor motion entry */
  740.     {
  741.         fprintf(stderr, "Sorry, for a ");        
  742.         fprintf(stderr, term);
  743.         fprintf(stderr, ", I can't find the cursor motion entry in termcap\n");
  744.         fflush(stderr);
  745.         exit(1);
  746.     }
  747.     if (!CE)    /* can't find clear to end of line entry */
  748.     {
  749.         fprintf(stderr, "Sorry, for a ");        
  750.         fprintf(stderr, term);
  751.         fprintf(stderr,", I can't find the clear to end of line entry in termcap\n");
  752.         fflush(stderr);
  753.         exit(1);
  754.     }
  755.     if (!CL)    /* can't find clear entire screen entry */
  756.     {
  757.         fprintf(stderr, "Sorry, for a ");        
  758.         fprintf(stderr, term);
  759.         fprintf(stderr, ", I can't find the clear entire screen entry in termcap\n");
  760.         fflush(stderr);
  761.         exit(1);
  762.     }
  763.     /* get memory for decoded output buffer*/
  764.     if ((outbuf=malloc(BUFBIG+16))==0) {
  765.       fprintf(stderr,"Error malloc'ing memory for decoded output buffer\n");
  766.         fflush(stderr);
  767.         died(-285);    /* malloc() failure */
  768.     }
  769. }
  770.  
  771. /*
  772.  * cl_line(x,y)  Clear the whole line indicated by 'y' and leave cursor at [x,y]
  773.  */
  774. cl_line(x,y)
  775. int x,y;
  776. {
  777.     cursor(1,y);        
  778.     *lpnt++ = CL_LINE;        
  779.     cursor(x,y);
  780. }
  781.  
  782. /*
  783.  * cl_up(x,y) Clear screen from [x,1] to current position. Leave cursor at [x,y]
  784.  */
  785. cl_up(x,y)
  786. register int x,y;
  787. {
  788.     register int i;
  789.     cursor(1,1);
  790.     for (i=1; i<=y; i++)   { 
  791.         *lpnt++ = CL_LINE;  
  792.         *lpnt++ = '\n'; 
  793.     }
  794.     cursor(x,y);
  795. }
  796.  
  797. /*
  798.  * cl_dn(x,y)     Clear screen from [1,y] to end of display. Leave cursor at [x,y]
  799.  */
  800. cl_dn(x,y)
  801. int x,y;
  802. {
  803.     int i;
  804.  
  805.     cursor(1,y);
  806.     if (!CD) {
  807.         *lpnt++ = CL_LINE;
  808.         for (i=y; i<=24; i++) { 
  809.             *lpnt++ = CL_LINE;  
  810.             if (i!=24) *lpnt++ = '\n'; 
  811.         }
  812.         cursor(x,y);
  813.     }
  814.     else
  815.         *lpnt++ = CL_DOWN;
  816.     cursor(x,y);
  817. }
  818.  
  819. /*
  820.  * standout(str)  Print the argument string in inverse video (standout mode).
  821.  */
  822. standout(str)
  823. register char *str;
  824. {
  825.     if (boldon == 0) {
  826.         lprcat(str);
  827.         return;
  828.     }
  829.     *lpnt++ = ST_START;
  830.     while (*str)
  831.         *lpnt++ = *str++;
  832.     *lpnt++ = ST_END;
  833. }
  834.  
  835. /*
  836.  * set_score_output()     Called when output should be literally printed.
  837.  */
  838. set_score_output()
  839. {
  840.     enable_scroll = -1;
  841. }
  842.  
  843. /*
  844.  *    lflush()                    Flush the output buffer
  845.  *
  846.  *    Returns nothing of value.
  847.  *    for termcap version: Flush output in output buffer according to output
  848.  *                    status as indicated by `enable_scroll'
  849.  */
  850. static int scrline=18; /* line # for wraparound instead of scrolling if no DL */
  851. lflush ()
  852. {
  853.     int lpoint;
  854.     char *str;
  855.     static int curx = 0;
  856.     static int cury = 0;
  857.  
  858.     if ((lpoint = lpnt - lpbuf) > 0) {
  859.         if (enable_scroll <= -1) {
  860.             flush_buf();
  861.             if (write(lfd,lpbuf,lpoint) != lpoint) {
  862.                    fprintf(stderr,"error writing to output file\n");
  863.                 fflush(stderr);
  864.             }
  865.             lpnt = lpbuf;    /* point back to beginning of buffer */
  866.             return;
  867.         }
  868.         for (str = lpbuf; str < lpnt; str++) {
  869.             if (*str>=32)    { 
  870.                 putcharacter (*str); 
  871.                 curx++; 
  872.             }
  873.             else switch (*str) {
  874.             case CLEAR:        
  875.                 tputs (CL, 0, putcharacter);        
  876.                 curx = cury = 0;
  877.                 break;
  878.  
  879.             case CL_LINE:    
  880.                 tputs (CE, 0, putcharacter);
  881.                 break;
  882.  
  883.             case CL_DOWN:    
  884.                 tputs (CD, 0, putcharacter);
  885.                 break;
  886.  
  887.             case ST_START:    
  888.                 tputs (SO, 0, putcharacter);
  889.                 break;
  890.  
  891.             case ST_END:    
  892.                 tputs (SE, 0, putcharacter);
  893.                 break;
  894.  
  895.             case CURSOR:    
  896.                 curx = *++str - 1;        
  897.                 cury = *++str - 1;
  898.                 tputs (tgoto (CM, curx, cury), 0, putcharacter);
  899.                 break;
  900.             case '\n':        
  901.                 if ((cury == 23) && enable_scroll) {
  902.                     if (!DL || !AL) {
  903.                         if (++scrline > 23) scrline=19;
  904.                         if (++scrline > 23) scrline=19;
  905.                         tputs (tgoto (CM, 0, scrline), 0, putcharacter);
  906.                         tputs (CE, 0, putcharacter);
  907.  
  908.                         if (--scrline < 19) scrline=23;
  909.                         tputs (tgoto (CM, 0, scrline), 0, putcharacter);
  910.                         tputs (CE, 0, putcharacter);
  911.                     }
  912.                     else {
  913.                         tputs (tgoto (CM, 0, 19), 0, putcharacter);
  914.                         tputs (DL, 0, putcharacter);
  915.                         tputs (tgoto (CM, 0, 23), 0, putcharacter);
  916.                     }
  917.                 }
  918.                 else {
  919.                     putcharacter ('\n');        
  920.                     cury++;
  921.                 }
  922.                 curx = 0;
  923.                 break;
  924.  
  925.             default:        
  926.                 putcharacter (*str); 
  927.                 curx++;
  928.             };
  929.         }
  930.     }
  931.     lpnt = lpbuf;
  932.     flush_buf();    /* flush real output buffer now */
  933. }
  934.  
  935. static int index=0;
  936.  
  937. /*
  938.  * putcharacter(ch)        Print one character in decoded output buffer.
  939.  */
  940. int putcharacter(c)
  941. int c;
  942. {
  943.     outbuf[index++] = c;
  944.     if (index >= BUFBIG)  
  945.         flush_buf();
  946. }
  947.  
  948. /*
  949.  * flush_buf()            Flush buffer with decoded output.
  950.  */
  951. flush_buf()
  952. {
  953.     if (index) 
  954.         write(lfd, outbuf, index);
  955.     index = 0;
  956. }
  957.  
  958. /*
  959.  *    char *tmcapcnv(sd,ss)  
  960.  *        Routine to convert vt100 escapes to termcap format
  961.  *
  962.  *    Processes only the \33[#m sequence (converts . files for termcap use 
  963.  */
  964. char *tmcapcnv(sd,ss)
  965. char *sd,*ss;
  966. {
  967.     int tmstate=0;    /* 0=normal, 1=\33 2=[ 3=# */
  968.     char tmdigit=0;    /* the # in \33[#m */
  969.  
  970.     while (*ss) {
  971.         switch(tmstate) {
  972.         case 0:    
  973.             if (*ss=='\33')  { 
  974.                 tmstate++; 
  975.                 break; 
  976.             }
  977. ign:  
  978.             *sd++ = *ss;
  979. ign2: 
  980.             tmstate = 0;
  981.             break;
  982.         case 1: 
  983.             if (*ss!='[') goto ign;
  984.             tmstate++;
  985.             break;
  986.         case 2: 
  987.             if (isdigit(*ss)) { 
  988.                 tmdigit= *ss-'0'; 
  989.                 tmstate++; 
  990.                 break; 
  991.             }
  992.             if (*ss == 'm') { 
  993.                 *sd++ = ST_END; 
  994.                 goto ign2; 
  995.             }
  996.             goto ign;
  997.         case 3: 
  998.             if (*ss == 'm') {
  999.                 if (tmdigit) *sd++ = ST_START;
  1000.                 else *sd++ = ST_END;
  1001.                 goto ign2;
  1002.             }
  1003.         default: 
  1004.             goto ign;
  1005.         };
  1006.         ss++;
  1007.     }
  1008.     *sd=0; /* 0 terminator */
  1009.     return(sd);
  1010. }
  1011.  
  1012. /*
  1013.  *    beep()    Routine to emit a beep if enabled (see no-beep in .Ularnopts)
  1014.  */
  1015. beep()
  1016. {
  1017.     if (!nobeep) *lpnt++ = '\7';
  1018. }
  1019.